﻿namespace Blaze.Editor
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Framework;
    using Framework.Logging;
    using UnityEditor;
    using UnityEngine;
    using Object = UnityEngine.Object;

    /// <summary>
    /// 在工程中筛选所有引用了指定资源的资源列表。
    /// </summary>
    public class AssetReferenceWindow : EditorWindow
    {
        [MenuItem("Assets/Find References In Project", false, 1)]
        public static void Open()
        {
            var window = GetWindow<AssetReferenceWindow>(false, "Asset Ref", true);
            window.mTarget = Selection.objects[0];
            window.search();
        }

        private static bool shouldCheckDependencies(string assetPath)
        {
            var extension = Path.GetExtension(assetPath);
            foreach (var item in mUnreferencableAssetExtensions)
            {
                if (string.Equals(extension, item, StringComparison.OrdinalIgnoreCase))
                    return false;
            }
            return true;
        }

        private void clear()
        {
            mMatchedObjects.Clear();
        }

        private void OnGUI()
        {
            EditorGUILayout.BeginHorizontal();
            mTarget = EditorGUILayout.ObjectField("Target:", mTarget, typeof (Object), false);
            if (GUILayout.Button("Search"))
                search();
            EditorGUILayout.EndHorizontal();
            GUILayout.Space(8);

            var tip = string.Format("{0} matched.", mMatchedObjects.Count);
            mFoldoutResult = EditorGUILayout.Foldout(mFoldoutResult, tip);
            if (!mFoldoutResult)
                return;
            mScroll = GUILayout.BeginScrollView(mScroll);
            for (var i = 0; i < mMatchedObjects.Count; i++)
            {
                var match = mMatchedObjects[i];
                if (match == null)
                    EditorGUILayout.LabelField("Destroyed");
                else
                    EditorGUILayout.ObjectField(match.name, match, typeof (GameObject), false);
            }
            GUILayout.EndScrollView();
        }

        private void search()
        {
            clear();
            if (mTarget == null)
                return;
            var targetAssetPath = AssetDatabase.GetAssetPath(mTarget);
            if (targetAssetPath == null)
                return;

            var assetPaths = AssetDatabase.GetAllAssetPaths();
            for (var i = 0; i < assetPaths.Length; i++)
            {
                var assetPath = assetPaths[i];
                if (!shouldCheckDependencies(assetPath))
                    continue;
                if (EditorUtility.DisplayCancelableProgressBar("Searching references...", assetPath, (float) i/assetPaths.Length))
                    break;

#if UNITY_4
                var dependencies = AssetDatabase.GetDependencies(new []{assetPath});
#else
                var dependencies = AssetDatabase.GetDependencies(assetPath, false);
#endif

                if (dependencies.Contains(targetAssetPath))
                    mMatchedObjects.Add(AssetDatabase.LoadMainAssetAtPath(assetPath));
            }
            EditorUtility.ClearProgressBar();
        }

        private static readonly Log mLog = LogManager.GetLogger(typeof (AssetReferenceWindow));
        private static readonly string[] mUnreferencableAssetExtensions = {".mp3", ".ogg", ".png", ".jpg", ".lua", ".meta"};
        private bool mFoldoutResult;
        private readonly List<Object> mMatchedObjects = new List<Object>();
        private Vector2 mScroll;
        private Object mTarget;
    }
}